#include "Renderer.h"
#include <SERender/Descriptors/FrameDescriptor.h>

namespace SEngine
{
    void Renderer::BeginFrame()
    {
        auto frameDescriptor = this->AnyDescriptor::GetDescriptor<FrameDescriptor>();
        if (frameDescriptor && m_fbo) {
            m_fbo->get().Resize(frameDescriptor->get().w, frameDescriptor->get().h);
            m_fbo->get().Use();
            m_fbo->get().Bind();
        }
        this->Descriptor<RenderFeature>::Foreach([](RenderFeature & elem) {
            elem.BeginFrame();
        });
        for (auto & task : m_tasks) {
            task->OnBeginFrame();
        }
        this->Descriptor<RenderPass>::Foreach([](RenderPass & elem) {
            elem.BeginFrame();
        });
    }

    void Renderer::DrawFrame()
    {
        for (auto & task : m_tasks) {
            task->OnDrawFrame();
        }
        this->Descriptor<RenderPass>::Foreach([](RenderPass & elem) {
            elem.DrawFrame();
        });
    }

    void Renderer::EndFrame()
    {
        this->Descriptor<RenderPass>::Foreach([](RenderPass & elem) {
            elem.EndFrame();
        });
        for (auto & task : m_tasks) {
            task->OnEndFrame();
        }
        this->Descriptor<RenderFeature>::Foreach([](RenderFeature & elem) {
            elem.EndFrame();
        });
        m_tasks.clear();
        if (m_fbo) {
            m_fbo->get().Unbind();
        }
    }

    void Renderer::DrawEntity(Drawable & entity)
    {
        entity.Draw(*this);
    }

    void Renderer::UseFrameBuffer(FrameBuffer &fbo, std::function<void(void)> &&fn)
    {
        if (m_fbo) {
            m_fbo->get().Unbind();
        }
        fbo.Bind();
        fn();
        fbo.Unbind(); 
        if (m_fbo) {
            m_fbo->get().Bind();
        }
    }

} // namespace SEngine


